/*
 * Copyright (C) 2007 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.epam.android.training.day6.provider;

import com.epam.android.training.SecretContacts;

import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.text.TextUtils;

import java.util.HashMap;

/**
 * Provides access to a secret database of secret contacts.
 */
public class SecretContactsProvider extends ContentProvider {

  private static final int CONTACTS = 1;

  private static final int CONTACT_ID = 2;

  private static final UriMatcher uriMatcher;

  private static HashMap<String, String> projectionMap;
  static {
    uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
    uriMatcher.addURI(SecretContacts.AUTHORITY, "secret_contacts", CONTACTS);
    uriMatcher.addURI(SecretContacts.AUTHORITY, "contacts/#", CONTACT_ID);

    projectionMap = new HashMap<String, String>();
    projectionMap.put(SecretContacts._ID, SecretContacts._ID);
    projectionMap.put(SecretContacts.NAME, SecretContacts.NAME);
    projectionMap.put(SecretContacts.MAIL, SecretContacts.MAIL);
  }

  private static final String TABLE_NAME = "secret_contacts";

  private static class DatabaseHelper extends SQLiteOpenHelper {

    private static final String DATABASE_NAME = "secret_contacts.db";

    private static final int DATABASE_VERSION = 2;

    DatabaseHelper(Context context) {
      super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
      db.execSQL("CREATE TABLE " + TABLE_NAME + " (" + SecretContacts._ID + " INTEGER PRIMARY KEY,"
          + SecretContacts.NAME + " TEXT," + SecretContacts.MAIL + " TEXT" + ");");

      ContentValues values = new ContentValues();
      values.put(SecretContacts.NAME, "Dark Imperor");
      values.put(SecretContacts.MAIL, "dark_imperor@dark_universe.com");
      db.insert(TABLE_NAME, SecretContacts.NAME, values);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
      db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
      onCreate(db);
    }
  }

  private DatabaseHelper dbHelper;

  @Override
  public boolean onCreate() {
    dbHelper = new DatabaseHelper(getContext());
    return true;
  }

  @Override
  public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
    SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();

    switch (uriMatcher.match(uri)) {
      case CONTACTS:
        queryBuilder.setTables(TABLE_NAME);
        queryBuilder.setProjectionMap(projectionMap);
        break;

      case CONTACT_ID:
        queryBuilder.setTables(TABLE_NAME);
        queryBuilder.setProjectionMap(projectionMap);
        queryBuilder.appendWhere(SecretContacts._ID + "=" + uri.getPathSegments().get(1));
        break;

      default:
        throw new IllegalArgumentException("Unknown URI " + uri);
    }

    if (TextUtils.isEmpty(sortOrder)) {
      sortOrder = SecretContacts.DEFAULT_SORT_ORDER;
    }
    SQLiteDatabase db = dbHelper.getReadableDatabase();
    Cursor cursor = queryBuilder.query(db, projection, selection, selectionArgs, null, null, sortOrder);
    cursor.setNotificationUri(getContext().getContentResolver(), uri);
    return cursor;
  }

  @Override
  public String getType(Uri uri) {
    switch (uriMatcher.match(uri)) {
      case CONTACTS:
        return SecretContacts.CONTENT_TYPE;

      case CONTACT_ID:
        return SecretContacts.CONTENT_ITEM_TYPE;

      default:
        throw new IllegalArgumentException("Unknown URI " + uri);
    }
  }

  @Override
  public Uri insert(Uri uri, ContentValues values) {
    if (uriMatcher.match(uri) != CONTACTS) {
      throw new IllegalArgumentException("Unknown URI " + uri);
    }
    if (values == null || !values.containsKey(SecretContacts.NAME) || !values.containsKey(SecretContacts.MAIL)) {
      throw new IllegalArgumentException("Unknown URI " + uri);
    }

    SQLiteDatabase db = dbHelper.getWritableDatabase();
    long rowId = db.insert(TABLE_NAME, SecretContacts.NAME, values);
    if (rowId > 0) {
      Uri contactUri = ContentUris.withAppendedId(SecretContacts.CONTENT_URI, rowId);
      getContext().getContentResolver().notifyChange(contactUri, null);
      return contactUri;
    }
    throw new SQLException("Failed to insert row into " + uri);
  }

  @Override
  public int delete(Uri uri, String where, String[] whereArgs) {
    SQLiteDatabase db = dbHelper.getWritableDatabase();
    int count;
    switch (uriMatcher.match(uri)) {
      case CONTACTS:
        count = db.delete(TABLE_NAME, where, whereArgs);
        break;
      case CONTACT_ID:
        String contactId = uri.getPathSegments().get(1);
        count = db.delete(TABLE_NAME, SecretContacts._ID + "=" + contactId
            + (!TextUtils.isEmpty(where) ? " AND (" + where + ')' : ""), whereArgs);
        break;
      default:
        throw new IllegalArgumentException("Unknown URI " + uri);
    }
    getContext().getContentResolver().notifyChange(uri, null);
    return count;
  }

  @Override
  public int update(Uri uri, ContentValues values, String where, String[] whereArgs) {
    SQLiteDatabase db = dbHelper.getWritableDatabase();
    int count;
    switch (uriMatcher.match(uri)) {
      case CONTACTS:
        count = db.update(TABLE_NAME, values, where, whereArgs);
        break;

      case CONTACT_ID:
        String contactId = uri.getPathSegments().get(1);
        count = db.update(TABLE_NAME, values, SecretContacts._ID + "=" + contactId
            + (!TextUtils.isEmpty(where) ? " AND (" + where + ')' : ""), whereArgs);
        break;

      default:
        throw new IllegalArgumentException("Unknown URI " + uri);
    }

    getContext().getContentResolver().notifyChange(uri, null);
    return count;
  }
}
